package com.wuyangnju.lj.simulation.master.model.snapshot;

import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import umontreal.iro.lecuyer.probdist.StudentDist;

import com.wuyangnju.lj.simulation.common.Plan;

public class ComputionDataSnapshot {
	private Map<Plan, PlanDataSnapshot> planDatas;

	public ComputionDataSnapshot(Map<Plan, PlanDataSnapshot> planDatas) {
		this.planDatas = planDatas;
	}

	public Map<Plan, PlanDataSnapshot> getPlanDatas() {
		return planDatas;
	}

	public List<Plan> currentPlans() {
		return new LinkedList<Plan>(planDatas.keySet());
	}

	public boolean ready(int threshold) {
		for (PlanDataSnapshot planData : planDatas.values()) {
			if (planData.getCount() < threshold) {
				return false;
			}
		}
		return true;
	}

	public boolean complete() {
		return planDatas.size() == 1;
	}

	public List<Plan> processForScreening(double alpha0, double k) {
		Set<Plan> planToRemove = new LinkedHashSet<Plan>();
		for (Plan planI : planDatas.keySet()) {
			for (Plan planJ : planDatas.keySet()) {
				if ((!planI.equals(planJ))
						&& (planDatas.get(planI).getCount() >= 10)
						&& (planDatas.get(planJ).getCount() >= 10)) {
					PlanDataSnapshot snapShotI = planDatas.get(planI);
					PlanDataSnapshot snapShotJ = planDatas.get(planJ);
					long samplen0i = snapShotI.getCount();
					long samplen0j = snapShotJ.getCount();

					double varFirsti = snapShotI.var_S2();
					double varFirstj = snapShotJ.var_S2();

					double tn0i = StudentDist.inverseF((int) samplen0i-1,
							Math.pow((1 - alpha0), 1.0 / (k - 1)));

					double tn0j = StudentDist.inverseF((int) samplen0j-1,
							Math.pow((1 - alpha0), 1.0 / (k - 1)));

					double wIJ = Math.sqrt(tn0i * tn0i * varFirsti / samplen0i
							+ tn0j * tn0j * varFirstj / samplen0j);

					double sampleMeani = snapShotI.avg_X();
					double sampleMeanj = snapShotJ.avg_X();

					double sampleDiff = sampleMeani - sampleMeanj;
               //for inventory
					if (sampleDiff >  wIJ) {
						planToRemove.add(planI);
						break;
					}
               //for three stage
               // if (sampleDiff < (-1) * wIJ) {
						//planToRemove.add(planI);
					  // break;
					//}
				}
			}
		}
		return new LinkedList<Plan>(planToRemove);
	}

	public List<Plan> process2(double alpha, double theta, double k) {
		double a = (-1) * (1 / theta)
				* Math.log(2 - 2 * Math.pow((1 - alpha), 1 / (k - 1)));
		double lambda = theta / 2;
		Set<Plan> planToRemove = new LinkedHashSet<Plan>();
		for (Plan planI : planDatas.keySet()) {
			for (Plan planJ : planDatas.keySet()) {
				if (!planI.equals(planJ)) {
					PlanDataSnapshot snapShotI = planDatas.get(planI);
					PlanDataSnapshot snapShotJ = planDatas.get(planJ);
					double deltaYij = snapShotI.fixedDeltaY(snapShotJ);
					double deltaZij = snapShotI.fixedDeltaZ(snapShotJ);
					if (deltaYij < Math.min(0, -a + lambda * deltaZij)) {
						planToRemove.add(planI);
						break;
					}
				}
			}
		}
		return new LinkedList<Plan>(planToRemove);

	}

	public List<Plan> process(double alpha, double theta, double k) {
		double a = (-1) * (1 / theta)
				* Math.log(2 - 2 * Math.pow((1 - alpha), 1 / (k - 1)));
		double lambda = theta / 2;
		Set<Plan> planToRemove = new LinkedHashSet<Plan>();
		for (Plan planI : planDatas.keySet()) {
			for (Plan planJ : planDatas.keySet()) {
				if (!planI.equals(planJ)) {
					PlanDataSnapshot snapShotI = planDatas.get(planI);
					PlanDataSnapshot snapShotJ = planDatas.get(planJ);
					double deltaYij = snapShotI.deltaY(snapShotJ);
					double deltaZij = snapShotI.deltaZ(snapShotJ);
					// I make a change here, this is for (s,S) inventory
					 if (deltaYij > Math.max(0, a - lambda * deltaZij)) {
					 planToRemove.add(planI);
					 break;
					 }
          // this is for three stage 
					//if (deltaYij < Math.min(0, -a + lambda * deltaZij)) {
					 // planToRemove.add(planI);
					 // break;
					//}
				}
			}
		}
		return new LinkedList<Plan>(planToRemove);
	}
}

